home *** CD-ROM | disk | FTP | other *** search
/ Gamers Delight 2 / Gamers Delight 2.iso / Aminet / game / board / GNUChess4_0_58.lha / gnuchess-4.0 / src / new / gnuan.c < prev    next >
C/C++ Source or Header  |  1992-08-26  |  20KB  |  938 lines

  1. /*
  2.  * gnuan.c - Analysis interface for gnuchess.
  3.  *
  4.  * Copyright (c) 1988,1989,1990 John Stanback
  5.  * Copyright (c) 1992 Free Software Foundation
  6.  *
  7.  * This file is part of GNU CHESS.
  8.  *
  9.  * GNU Chess is free software; you can redistribute it and/or modify
  10.  * it under the terms of the GNU General Public License as published by
  11.  * the Free Software Foundation; either version 2, or (at your option)
  12.  * any later version.
  13.  *
  14.  * GNU Chess is distributed in the hope that it will be useful,
  15.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17.  * GNU General Public License for more details.
  18.  *
  19.  * You should have received a copy of the GNU General Public License
  20.  * along with GNU Chess; see the file COPYING.  If not, write to
  21.  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  22.  */
  23.  
  24. /*
  25.  * This is a front end for a chess analysis program.  It takes a file of
  26.  * moves in algebraic notation and creates a file containing each move that
  27.  * was made, the move it would have made, the score it would give itself
  28.  * after making the move it recommended, and the depth it searched for the
  29.  * move.
  30.  *
  31.  * This is a modification of nondsp.c.  I have cut out code that was not needed
  32.  * for this application such as the help and edit functions.  Most of the
  33.  * modifications were done in InputCommand.
  34.  */
  35.  
  36. /*
  37.  * This file will generate two different analysis programs.  One is meant to
  38.  * be run as a background process inwhich the in and out files are
  39.  * predefined. The other is meant to be run in the foreground where it will
  40.  * prompt you for the name of the file with the game in it, the maximum depth
  41.  * the search should be conducted to and the time limit per move.  It would
  42.  * be nice to be able to give these parameters on the command line, but that
  43.  * would mean changing main which is in the gnuchess.c file.
  44.  *
  45.  * For each move it will analyse the move until either it has run out of time or
  46.  * it has reached the maximum depth.
  47.  *
  48.  * To build the version for background processing define BACKGROUND_ANALYSIS
  49.  * either at the top of this file, or in compilation.  The files and depth
  50.  * used are defined below.  They are MAX_DEPTH, MAX_TIME, OUT_FILE, IN_FILE
  51.  * and PROG_FILE.  The PROG_FILE is a file that will be updated as each move
  52.  * is analysed so you can check its progress.  This is only updated when
  53.  * running the BACKGROUND_ANALYSIS version.  In the version where the
  54.  * filename and depth are entered at runtime, the output goes to stdout.
  55.  */
  56.  
  57. /* #define BACKGROUND_ANALYSIS 1 */
  58.  
  59. #define MAX_DEPTH  15
  60. #define MAX_TIME   20
  61. #define OUT_FILE   "/pad/gnuan.out"
  62. #define IN_FILE    "/pad/gnuan.in"
  63. #define PROG_FILE  "/pad/gnuan.prog"
  64.  
  65.  
  66. #include <ctype.h>
  67. #include <signal.h>
  68. #ifdef MSDOS
  69. #include <dos.h>
  70. #include <conio.h>
  71. #include <stdlib.h>
  72. #include <string.h>
  73. #include <time.h>
  74. #else
  75. #include <sys/param.h>
  76. #include <sys/types.h>
  77. #include <sys/file.h>
  78. #include <sys/ioctl.h>
  79. void TerminateSearch (int), Die (int);
  80.  
  81. #endif /* MSDOS */
  82.  
  83. #include "gnuchess.h"
  84. #include "ataks.h"
  85. #undef rxx
  86. #undef cxx
  87. #undef scanz
  88. #undef printz
  89.  
  90. #define rxx "12345678"
  91. #define cxx "abcdefgh"
  92. #define scanz scanf
  93. #define printz printf
  94.  
  95. char mvstr[4][6];
  96. extern char *ColorStr[2];
  97. int mycnt1, mycnt2;
  98.  
  99. static FILE *fpin;
  100. static FILE *fpout;
  101. char *DRAW;
  102. unsigned short int MV[MAXDEPTH];
  103. enum
  104. {
  105.   XBOARD, GNUCHESS, OTHER
  106. } InFileType;
  107. char InBuf[256];
  108.  
  109. #ifdef BACKGROUND_ANALYSIS
  110. static FILE *fpprog;
  111.  
  112. #endif
  113. static char white_actual_move[20];
  114. static char black_actual_move[20];
  115. static char white_suggest_move[20];
  116. static char black_suggest_move[20];
  117. static int white_score;
  118. static int black_score;
  119. static int white_moving;
  120. static int current_depth;
  121. static int current_score;
  122. static int enable_update_display = 0;
  123.  
  124.  
  125. void
  126. Initialize (void)
  127. {
  128.   mycnt1 = mycnt2 = 0;
  129. }
  130.  
  131. void
  132. ExitChess (void)
  133. {
  134.   ListGame ();
  135.   exit (0);
  136. }
  137.  
  138. #ifndef MSDOS            /* never called!!! */
  139. void
  140. Die (int sig)
  141. {
  142.   ExitChess ();
  143. }
  144.  
  145. #endif /* MSDOS */
  146.  
  147. void
  148. TerminateSearch (int sig)
  149. {
  150. #ifdef MSDOS
  151.   sig++;            /* shut up the compiler */
  152. #endif /* MSDOS */
  153.   if (!flag.timeout)
  154.     flag.musttimeout = true;
  155.   flag.bothsides = false;
  156. }
  157.  
  158. void
  159. algbr (short int f, short int t, short int flag)
  160.  
  161. /*
  162.  * Generate move strings in different formats.
  163.  */
  164.  
  165. {
  166.   int m3p;
  167.  
  168.   if (f != t)
  169.     {
  170.       /* algebraic notation */
  171.       mvstr[0][0] = cxx[column (f)];
  172.       mvstr[0][1] = rxx[row (f)];
  173.       mvstr[0][2] = cxx[column (t)];
  174.       mvstr[0][3] = rxx[row (t)];
  175.       mvstr[0][4] = mvstr[3][0] = '\0';
  176.       if (((mvstr[1][0] = pxx[board[f]]) == 'P') || (flag & promote))
  177.     {
  178.       if (mvstr[0][0] == mvstr[0][2])    /* pawn did not eat */
  179.         {
  180.           mvstr[2][0] = mvstr[1][0] = mvstr[0][2];    /* to column */
  181.           mvstr[2][1] = mvstr[1][1] = mvstr[0][3];    /* to row */
  182.           m3p = 2;
  183.         }
  184.       else
  185.         /* pawn ate */
  186.         {
  187.           mvstr[2][0] = mvstr[1][0] = mvstr[0][0];    /* from column */
  188.           mvstr[2][1] = mvstr[1][1] = mvstr[0][2];    /* to column */
  189.           mvstr[2][2] = mvstr[0][3];
  190.           m3p = 3;        /* to row */
  191.         }
  192.       mvstr[2][m3p] = mvstr[1][2] = '\0';
  193.       if (flag & promote)
  194.         {
  195.           mvstr[0][4] = mvstr[1][2] = mvstr[2][m3p] = qxx[flag & pmask];
  196.           mvstr[1][3] = mvstr[2][m3p + 1] = mvstr[0][5] = '\0';
  197.         }
  198.     }
  199.       else
  200.     /* not a pawn */
  201.     {
  202.       mvstr[2][0] = mvstr[1][0];
  203.       mvstr[2][1] = mvstr[0][1];
  204.       mvstr[2][2] = mvstr[1][1] = mvstr[0][2];    /* to column */
  205.       mvstr[2][3] = mvstr[1][2] = mvstr[0][3];    /* to row */
  206.       mvstr[2][4] = mvstr[1][3] = '\0';
  207.       strcpy (mvstr[3], mvstr[2]);
  208.       mvstr[3][1] = mvstr[0][0];
  209.       if (flag & cstlmask)
  210.         {
  211.           if (t > f)
  212.         {
  213.           strcpy (mvstr[1], "o-o");
  214.           strcpy (mvstr[2], "O-O");
  215.         }
  216.           else
  217.         {
  218.           strcpy (mvstr[1], "o-o-o");
  219.           strcpy (mvstr[2], "O-O-O");
  220.         }
  221.         }
  222.     }
  223.     }
  224.   else
  225.     mvstr[0][0] = mvstr[1][0] = mvstr[2][0] = mvstr[3][0] = '\0';
  226. }
  227.  
  228.  
  229. int
  230. VerifyMove (char *s, short int iop, unsigned short int *mv)
  231.  
  232. /*
  233.  * Compare the string 's' to the list of legal moves available for the
  234.  * opponent. If a match is found, make the move on the board.
  235.  */
  236.  
  237. {
  238.   static short pnt, tempb, tempc, tempsf, tempst, cnt;
  239.   static struct leaf xnode;
  240.   struct leaf *node;
  241.  
  242.   *mv = 0;
  243.   if (iop == 2)
  244.     {
  245.       UnmakeMove (opponent, &xnode, &tempb, &tempc, &tempsf, &tempst);
  246.       return (false);
  247.     }
  248.   cnt = 0;
  249.   MoveList (opponent, 2);
  250.   pnt = TrPnt[2];
  251.   while (pnt < TrPnt[3])
  252.     {
  253.       node = &Tree[pnt++];
  254.       algbr (node->f, node->t, (short) node->flags);
  255.       if (strcmp (s, mvstr[0]) == 0 || strcmp (s, mvstr[1]) == 0 ||
  256.       strcmp (s, mvstr[2]) == 0 || strcmp (s, mvstr[3]) == 0)
  257.     {
  258.       cnt++;
  259.       xnode = *node;
  260.     }
  261.     }
  262.   if (cnt == 1)
  263.     {
  264.       MakeMove (opponent, &xnode, &tempb, &tempc, &tempsf, &tempst, &INCscore);
  265.       if (SqAtakd (PieceList[opponent][0], computer))
  266.     {
  267.       UnmakeMove (opponent, &xnode, &tempb, &tempc, &tempsf, &tempst);
  268.       printz ("Illegal move\n");
  269.       return (false);
  270.     }
  271.       else
  272.     {
  273.       if (iop == 1)
  274.         return (true);
  275.  
  276.       /*
  277.            * UpdateDisplay (xnode.f, xnode.t, 0, (short) xnode.flags);
  278.            */
  279.       if ((board[xnode.t] == pawn)
  280.           || (xnode.flags & capture)
  281.           || (xnode.flags & cstlmask))
  282.         {
  283.           Game50 = GameCnt;
  284.           ZeroRPT ();
  285.         }
  286.       GameList[GameCnt].depth = GameList[GameCnt].score = 0;
  287.       GameList[GameCnt].nodes = 0;
  288.       ElapsedTime (1);
  289.       GameList[GameCnt].time = (short) et;
  290.       TimeControl.clock[opponent] -= et;
  291.       --TimeControl.moves[opponent];
  292.       *mv = (xnode.f << 8) | xnode.t;
  293.       algbr (xnode.f, xnode.t, false);
  294.       return (true);
  295.     }
  296.     }
  297. #ifdef CHESSTOOL
  298.   printz ("Illegal move\n");
  299. #else
  300.   if (cnt > 1)
  301.     ShowMessage ("Ambiguous Move!");
  302. #endif
  303.   return (false);
  304. }
  305.  
  306. void
  307. help (void)
  308. {
  309. }
  310.  
  311. void
  312. EditBoard (void)
  313.  
  314. /*
  315.  * Set up a board position. Pieces are entered by typing the piece followed
  316.  * by the location. For example, Nf3 will place a knight on square f3.
  317.  */
  318.  
  319. {
  320. }
  321.  
  322. void
  323. SetupBoard (void)
  324.  
  325. /*
  326.  * Compatibility with Unix chess and the nchesstool. Set up a board position.
  327.  * Eight lines of eight characters are used to setup the board. a8-h8 is the
  328.  * first line. Black pieces are  represented  by  uppercase characters.
  329.  */
  330.  
  331. {
  332. }
  333.  
  334. void
  335. ShowDepth (char ch)
  336. {
  337. #ifdef MSDOS
  338.   ch++;                /* shut up the compiler */
  339. #endif /* MSDOS */
  340. }
  341.  
  342. void
  343. ShowResults (short int score, unsigned short int *bstline, char ch)
  344. {
  345.   int i;
  346.  
  347.   current_score = score;
  348.   current_depth = Sdepth;
  349.   for (i = 1; bstline[i] > 0; i++)
  350.     {
  351.       MV[i] = bstline[i];
  352.     } MV[i] = 0;
  353. }
  354.  
  355. void
  356. SearchStartStuff (short int side)
  357. {
  358.   signal (SIGINT, TerminateSearch);
  359. #ifndef MSDOS
  360.   signal (SIGQUIT, TerminateSearch);
  361. #endif /* MSDOS */
  362.   if (flag.post)
  363.     {
  364.       fprintf (stderr, "\nMove# %d    Target= %ld    Clock: %ld\n",
  365.            TCmoves - TimeControl.moves[side] + 1,
  366.            ResponseTime, TimeControl.clock[side]);
  367.     }
  368. }
  369.  
  370. void
  371. OutputMove (void)
  372. {
  373.   if (white_moving)
  374.     {
  375.       strcpy (white_suggest_move, mvstr[0]);
  376.       white_score = current_score;
  377.     }
  378.   else
  379.     {
  380.       strcpy (black_suggest_move, mvstr[0]);
  381.       black_score = current_score;
  382.     }
  383. }
  384.  
  385. void
  386. ElapsedTime (short int iop)
  387.  
  388. /*
  389.  * Determine the time that has passed since the search was started. If the
  390.  * elapsed time exceeds the target (ResponseTime+ExtraTime) then set timeout
  391.  * to true which will terminate the search.
  392.  */
  393. {
  394.   if (ahead)
  395.     {
  396. #ifndef MSDOS
  397. #ifdef FIONREAD
  398.       long nchar;
  399.  
  400.       ioctl (0, FIONREAD, &nchar);
  401.       if (nchar)
  402.     {
  403.       flag.timeout = true;
  404.       flag.bothsides = false;
  405.     }
  406. #endif
  407. #else
  408.       if (kbhit ())
  409.     {
  410.       flag.timeout = true;
  411.       flag.bothsides = false;
  412.     }
  413. #endif /* MSDOS */
  414.     }
  415.   et = (time ((long *) 0) - time0) * 100;
  416.   if (et < 0)
  417.     et = 0;
  418.   ETnodes += ZNODES;
  419.   if (iop == 1)
  420.     {
  421.       if (et > ResponseTime + ExtraTime && Sdepth > 1)
  422.     flag.timeout = true;
  423.       time0 = time ((long *) 0);
  424.       ETnodes = NodeCnt + ZNODES;
  425.     }
  426. }
  427.  
  428. void
  429. SetTimeControl (void)
  430. {
  431.   if (TCflag)
  432.     {
  433.       TimeControl.moves[white] = TimeControl.moves[black] = TCmoves;
  434.       TimeControl.clock[white] = TimeControl.clock[black] = 6000L * TCminutes;
  435.     }
  436.   else
  437.     {
  438.       TimeControl.moves[white] = TimeControl.moves[black] = 0;
  439.       TimeControl.clock[white] = TimeControl.clock[black] = 0;
  440.       MaxResponseTime = 6000L * TCminutes;
  441.     }
  442.   et = 0;
  443.   ElapsedTime (1);
  444. }
  445.  
  446. void
  447. ClrScreen (void)
  448. {
  449. #ifndef CHESSTOOL
  450.   printz ("\n");
  451. #endif
  452. }
  453.  
  454. void
  455. UpdateDisplay (short int f, short int t, short int redraw, short int isspec)
  456. {
  457. #ifndef CHESSTOOL
  458.   short r, c, l;
  459.  
  460.   if (!enable_update_display)
  461.     return;
  462.   if (redraw)
  463.     {
  464.       fprintf (fpout, "\n");
  465.       for (r = 7; r >= 0; r--)
  466.     {
  467.       for (c = 0; c <= 7; c++)
  468.         {
  469.           l = locn (r, c);
  470.           if (color[l] == neutral)
  471.         fprintf (fpout, " -");
  472.           else if (color[l] == white)
  473.         fprintf (fpout, " %c", qxx[board[l]]);
  474.           else
  475.         fprintf (fpout, " %c", pxx[board[l]]);
  476.         }
  477.       fprintf (fpout, "\n");
  478.     }
  479.       fprintf (fpout, "\n");
  480.     }
  481. #endif /* CHESSTOOL */
  482. #ifdef MSDOS
  483.   f++;
  484.   t++;
  485.   isspec++;            /* shut up the compiler */
  486. #endif /* MSDOS */
  487. }
  488.  
  489. void
  490. GetGame (void)
  491. {
  492. }
  493.  
  494. void
  495. SaveGame (void)
  496. {
  497. }
  498.  
  499. void
  500. ListGame (void)
  501. {
  502. }
  503.  
  504.  
  505.  
  506. void
  507. Undo (void)
  508.  
  509. /*
  510.  * Undo the most recent half-move.
  511.  */
  512.  
  513. {
  514.   short f, t;
  515.  
  516.   f = GameList[GameCnt].gmove >> 8;
  517.   t = GameList[GameCnt].gmove & 0xFF;
  518.   if (board[t] == king && distance (t, f) > 1)
  519.     (void) castle (GameList[GameCnt].color, f, t, 2);
  520.   else
  521.     {
  522.       /* Check for promotion: */
  523.       if (GameList[GameCnt].flags & promote)
  524.     {
  525.       board[t] = pawn;
  526.     }
  527.       board[f] = board[t];
  528.       color[f] = color[t];
  529.       board[t] = GameList[GameCnt].piece;
  530.       color[t] = GameList[GameCnt].color;
  531.       if (color[t] != neutral)
  532.     Mvboard[t]--;
  533.       Mvboard[f]--;
  534.     }
  535.   if (GameList[GameCnt].flags & epmask)
  536.     EnPassant (color[t], f, t, 2);
  537.   if (TCflag)
  538.     ++TimeControl.moves[color[f]];
  539.   GameCnt--;
  540.   computer = otherside[computer];
  541.   opponent = otherside[opponent];
  542.   flag.mate = false;
  543.   Sdepth = 0;
  544.   InitializeStats ();
  545. }
  546.  
  547. void
  548. ShowMessage (char *s)
  549. {
  550.   fprintf (stderr, "%s\n", s);
  551. }
  552.  
  553. void
  554. ShowSidetoMove (void)
  555. {
  556. }
  557.  
  558. void
  559. PromptForMove (void)
  560. {
  561. #ifndef CHESSTOOL
  562.   printz ("\nYour move is? ");
  563. #endif /* CHESSTOOL */
  564. }
  565.  
  566.  
  567. void
  568. ShowCurrentMove (short int pnt, short int f, short int t)
  569. {
  570. #ifdef MSDOS
  571.   f++;
  572.   t++;
  573.   pnt++;            /* shut up the compiler */
  574. #endif /* MSDOS */
  575. }
  576.  
  577. void
  578. ChangeAlphaWindow (void)
  579. {
  580.   printz ("window: ");
  581. }
  582.  
  583. void
  584. ChangeBetaWindow (void)
  585. {
  586.   printz ("window: ");
  587. }
  588.  
  589. void
  590. GiveHint (void)
  591. {
  592.   algbr ((short) (hint >> 8), (short) (hint & 0xFF), false);
  593.   fprintf (stderr, "Hint: %s\n", mvstr[0]);
  594. }
  595.  
  596. void
  597. SelectLevel (void)
  598. {
  599. }
  600.  
  601. void
  602. ChangeSearchDepth (void)
  603. {
  604.   printz ("depth= ");
  605.   scanz ("%hd", &MaxSearchDepth);
  606. }
  607.  
  608. void
  609. SetContempt (void)
  610. {
  611.   printz ("contempt= ");
  612.   scanz ("%hd", &contempt);
  613. }
  614.  
  615. void
  616. ChangeXwindow (void)
  617. {
  618.   printz ("xwndw= ");
  619.   scanz ("%hd", &xwndw);
  620. }
  621.  
  622. void
  623. TestSpeed (void (*f) (short int side, short int ply))
  624. {
  625.   short i;
  626.   long cnt, rate, t1, t2;
  627.  
  628.   t1 = time (0);
  629.   for (i = 0; i < 10000; i++)
  630.     {
  631.       f (opponent, 2);
  632.     }
  633.   t2 = time (0);
  634.   cnt = 10000L * (TrPnt[3] - TrPnt[2]);
  635.   rate = cnt / (t2 - t1);
  636.   printz ("Nodes= %ld Nodes/sec= %ld\n", cnt, rate);
  637. }
  638.  
  639.  
  640. int
  641. GetNextMove (char *buffer)
  642. {
  643.   char current;
  644.  
  645.   while (true)
  646.     {
  647.       while ((current = fgetc (fpin)) == ' ' || current == '\n') ;
  648.       if ((current != EOF) && (isdigit (current) || current == '-'))
  649.     {
  650.       while ((current = fgetc (fpin)) != ' ' && current != EOF) ;
  651.       if (current == EOF)
  652.         return 0;
  653.       else
  654.         continue;
  655.     }
  656.       if (current == EOF)
  657.     return (0);
  658.       while (current != ' ' && current != '\n' && current != EOF)
  659.     {
  660.       if (!(current == '-' || current == 'x' || current == 'X'))
  661.         {
  662.           *buffer++ = current;
  663.         }
  664.       current = fgetc (fpin);
  665.     }
  666.       *buffer = '\0';
  667.       return (1);
  668.     }
  669. }
  670.  
  671. void
  672. InputCommand (void)
  673.  
  674. /*
  675.  * Open the file of moves to analyse.  Go through the file move by move and
  676.  * do the following for each move.  See what gnuchess would have done in that
  677.  * position.  Record the move it would have made along with the score it
  678.  * would have given and the search depth.  Take back its move. Force the move
  679.  * that was actually made.  Keep track of statistics such as how many moves
  680.  * agreed.
  681.  */
  682.  
  683. {
  684.   int i;
  685.   short ok, tmp;
  686.   int search_depth, max_minutes;
  687.   long cnt, rate, t1, t2;
  688.   unsigned short mv;
  689.   char s[80];
  690.   char infilename[255];
  691.   char outfilename[255];
  692.   char progfilename[255];
  693.   char inbuf[256];
  694.   int move_number = 1;
  695.   long start_time, end_time, elapsed_time;
  696.   int total_black_moves, total_white_moves;
  697.   int same_black_moves, same_white_moves;
  698.   float white_percent, black_percent;
  699.  
  700.   /* Initialize necessary variables. */
  701.  
  702.   flag.quit = false;
  703.   flag.beep = false;
  704.   player = opponent;
  705.   enable_update_display = 1;
  706.   ft = 0;
  707.   Book = false;
  708.   total_black_moves = 0;
  709.   total_white_moves = 0;
  710.   same_black_moves = 0;
  711.   same_white_moves = 0;
  712.  
  713. #ifdef BACKGROUND_ANALYSIS
  714.  
  715.   /*
  716.    * Set the in files to standard ones for analysis if background
  717.    * processing selected.
  718.    */
  719.  
  720.   strcpy (infilename, IN_FILE);
  721.   strcpy (outfilename, OUT_FILE);
  722.   strcpy (progfilename, PROG_FILE);
  723.   fpout = fopen (outfilename, "w");
  724.   if (fpout == NULL)
  725.     {
  726.       fprintf (fpout, "This file does not exist : %s\n", outfilename);
  727.       flag.quit = 1;
  728.       return;
  729.     }
  730.   MaxSearchDepth = MAX_DEPTH;
  731.   TCminutes = MAX_TIME;
  732.  
  733. #else
  734.  
  735.   /* Request information on where the file is and the depth an time. */
  736.  
  737.   fpout = stderr;
  738.   fprintf (fpout, "Input the file with the algebraic moves of the game.\n");
  739.   fflush(fpout);
  740.   gets (infilename);
  741.   fprintf (fpout, "\n");
  742.   do
  743.     {
  744.       fprintf (fpout, "Input the search depth you want to use.  (1 to 29)\n");
  745.       gets (inbuf);
  746.       search_depth = atoi (inbuf);
  747.   } while (search_depth < 1 || search_depth > 29);
  748.   MaxSearchDepth = search_depth;
  749.  
  750.   fprintf (fpout, "\n");
  751.   do
  752.     {
  753.       fprintf (fpout, "Input the maximum number of minutes per move you want to use.\n");
  754.       gets (inbuf);
  755.       max_minutes = atoi (inbuf);
  756.   } while (max_minutes < 1);
  757.   printf ("\nYou will search to %d half moves\n", search_depth);
  758.   printf ("\nWith no search taking more than %d minutes\n",max_minutes);
  759.   TCminutes = max_minutes;
  760.  
  761.   fprintf (fpout, "\n\n");
  762.  
  763. #endif
  764.  
  765.   fpin = fopen (infilename, "r");
  766.   if (fpin == NULL)
  767.     {
  768.       fprintf (fpout, "This file does not exist : %s\n", infilename);
  769.       flag.quit = 1;
  770.       return;
  771.     }
  772.   /* lets find out about this file */
  773.   fgets (InBuf, 256, fpin);
  774.   InFileType = OTHER;
  775.   if (!strncmp (InBuf, "xboard", 6))
  776.     {
  777.       InFileType = XBOARD;
  778.       fgets (InBuf, 256, fpin);
  779.       fgets (InBuf, 256, fpin);
  780.     }
  781.   else if (!strncmp (InBuf, "gnuchess", 6))
  782.     {
  783.       InFileType = GNUCHESS;
  784.       fgets (InBuf, 256, fpin);
  785.     }
  786.   else
  787.     rewind (fpin);
  788.   TCmoves = 1;
  789.   TCflag = (TCmoves > 1);
  790.   OperatorTime = 0;
  791.   SetTimeControl ();
  792.  
  793.   fpout = stdout;
  794.  
  795.   fprintf (fpout, "Move White Black      Score Depth     Best Line\n");
  796.   fprintf (fpout, "------------------------------------------------------------------\n");
  797.  
  798. #ifdef BACKGROUND_ANALYSIS
  799.  
  800.   /*
  801.    * Update progress in the progress file if this is running in the
  802.    * background.
  803.    */
  804.  
  805.   fpprog = fopen (progfilename, "w");
  806.   fprintf (fpprog, "Done with move #%d.\n", move_number - 1);
  807.   fclose (fpprog);
  808.  
  809. #endif
  810.  
  811.   time (&start_time);
  812.   while (1)
  813.     {
  814.       opponent = black;
  815.       computer = white;
  816.       player = computer;
  817.       white_moving = 1;
  818.       if (!GetNextMove (s))
  819.     {
  820.       flag.quit = 1;
  821.       break;
  822.     }
  823.       if (!strcmp (s, "Black") || !strcmp (s, "White") || !strcmp (s, "draw"))
  824.     break;
  825.       flag.force = 0;
  826.       SelectMove (computer, 1);
  827.       Undo ();
  828.       flag.force = 1;
  829.       opponent = white;
  830.       computer = black;
  831.       player = opponent;
  832.       ok = VerifyMove (s, 0, &mv);
  833.       if (!ok)
  834.     {
  835.       fprintf (fpout, "\nBad move.  %s  Board position is: \n", s);
  836.       UpdateDisplay (0, 0, 1, 0);
  837.       flag.quit = 1;
  838.       break;
  839.     }
  840.       else
  841.     {
  842.       char ch, x[80];
  843.       strcpy (white_actual_move, s);
  844.       strcpy (x, white_actual_move);
  845.       if (strcmp (white_actual_move, white_suggest_move))
  846.         strcat (x, "*");
  847.       fprintf (fpout, "%3d   %-9s      %5d%5d   ", move_number, x, white_score, current_depth);
  848.       for (i = 1; MV[i] > 0; i++)
  849.         {
  850.           algbr ((short) (MV[i] >> 8), (short) (MV[i] & 0xFF), false);
  851.           printf ("%5s ", mvstr[0]);
  852.         }
  853.       printf ("\n");
  854.       fflush (fpout);
  855.       move_number++;
  856.       total_white_moves++;
  857.       if (!strcmp (white_actual_move, white_suggest_move))
  858.         same_white_moves++;
  859.       Sdepth = 0;
  860.       ft = 0;
  861.     }
  862.       player = computer;
  863.       white_moving = 0;
  864.       if (!GetNextMove (s))
  865.     {
  866.       flag.quit = 1;
  867.       break;
  868.     }
  869.       if (!strcmp (s, "Black") || !strcmp (s, "White") || !strcmp (s, "draw"))
  870.     break;
  871.       flag.force = 0;
  872.       SelectMove (computer, 1);
  873.       Undo ();
  874.       flag.force = 1;
  875.       opponent = black;
  876.       computer = white;
  877.       player = opponent;
  878.       ok = VerifyMove (s, 0, &mv);
  879.       if (!ok)
  880.     {
  881.       fprintf (fpout, "\nBad move.  %s  Board position is: \n", s);
  882.       UpdateDisplay (0, 0, 1, 0);
  883.       flag.quit = 1;
  884.       break;
  885.     }
  886.       else
  887.     {
  888.       char x[8];
  889.       strcpy (black_actual_move, s);
  890.       strcpy (x, black_actual_move);
  891.       if (strcmp (black_actual_move, black_suggest_move))
  892.         strcat (x, "*");
  893.       fprintf (fpout, "            %-9s%5d%5d   ", x, black_score, current_depth);
  894.       for (i = 1; MV[i] > 0; i++)
  895.         {
  896.           algbr ((short) (MV[i] >> 8), (short) (MV[i] & 0xFF), false);
  897.           printf ("%5s ", mvstr[0]);
  898.         }
  899.       printf ("\n");
  900.       fflush (fpout);
  901.  
  902. #ifdef BACKGROUND_ANALYSIS
  903.  
  904.       /*
  905.            * Update progress in the progress file if this is running in the
  906.            * background.
  907.            */
  908.  
  909.       fpprog = fopen (progfilename, "w");
  910.       fprintf (fpprog, "Done with move #%d.\n", move_number - 1);
  911.       fclose (fpprog);
  912. #else
  913.  
  914.       /*
  915.            * fprintf(stderr, "Done with move #%d.\n", move_number-1);
  916.            */
  917.  
  918. #endif
  919.  
  920.       total_black_moves++;
  921.       if (!strcmp (black_actual_move, black_suggest_move))
  922.         same_black_moves++;
  923.       Sdepth = 0;
  924.       ft = 0;
  925.     }
  926.     }
  927.  
  928.   white_percent = ((float) same_white_moves) * 100 / (float) total_white_moves;
  929.   black_percent = ((float) same_black_moves) * 100 / (float) total_black_moves;
  930.   fprintf (fpout, "\n           White's percentage was %5.2f%%.     Black's percentage was %5.2f%%.\n", white_percent, black_percent);
  931.   time (&end_time);
  932.   elapsed_time = end_time - start_time;
  933.   fprintf (fpout, "\n           Elapsed time was %d seconds.\n", elapsed_time);
  934.   fclose (fpin);
  935.   fclose (fpout);
  936.   exit (0);
  937. }
  938.